package cn.changhong.user.filter;


import cn.changhong.user.aop.ResultBean;
import cn.changhong.user.exception.WrongPasswordException;
import cn.changhong.user.util.TokenAuthenticationService;
import net.sf.json.JSONObject;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * @author itguang
 * @create 2018-01-02 13:48
 **/
public class JWTLoginFilter extends   AbstractAuthenticationProcessingFilter {
    private AuthenticationManager authenticationManager;

    /**
     * @param url                   拦截的登陆URL地址
     * @param authenticationManager
     */
    public JWTLoginFilter(String url, AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher(url, "POST"));
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        ArrayList authorities = new ArrayList<>();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email, password, authorities);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        return authenticate;
    }


    /**
     * 登陆成功后,此方法会被调用,因此我们可以在次方法中生成token,并返回给客户端
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) {
        TokenAuthenticationService.addAuthentication(response, authResult);
    }

    /**
     * 登陆失败后,此方法会被调用,将失败的异常信息反馈到前端
     *
     * @param request
     * @param response
     * @param  failed
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter out = response.getWriter();
            ResultBean resultBean=new ResultBean();
            if(failed instanceof WrongPasswordException){
                resultBean=new ResultBean<String>(failed,ResultBean.UNEXPECTED);
            }else if(failed instanceof UsernameNotFoundException){
                resultBean=new ResultBean<String>(failed,ResultBean.NOTFOUND);
            }else {
                resultBean=new ResultBean<String>(failed,0);
            }
            JSONObject jsonObject=JSONObject.fromObject(resultBean);
            out.print(jsonObject.toString());
            out.flush();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}